import json
from core import edit_distance
from tqdm import tqdm
from terminaltables import SingleTable
import os

def merge_lists_to_jsonl(rets, output_path):
    """
    函数 `merge_lists_to_jsonl` 获取字典列表并将它们写入 JSONL 文件。
    :param rets: `rets` 参数是一个字典列表。每个字典代表需要写入输出文件的记录或项目。
    :param output_path: output_path 参数是将创建 JSONL 文件的文件路径。它应该是一个表示文件路径的字符串，包括文件名和扩展名。例如，“output.jsonl”。
    """
    with open(output_path, 'w', encoding='utf-8') as f:
        for ret in rets:
            json_line = json.dumps(ret, ensure_ascii=False)
            f.write(json_line + '\n')

def remove_string(string_list, target_string):
    """
    该函数从字符串列表中删除特定字符串。
    :param string_list: 要从中删除特定字符串的字符串列表。
    :param target_string: 您要从列表中删除的字符串。
    :return: 一个新列表，其中包含原始列表中除目标字符串之外的所有字符串。
    """
    return [s for s in string_list if s != target_string]

def remove_contained_strings(string_list):
    """
    该函数从列表中删除包含在同一列表中其他字符串中的字符串。
    
    :param string_list: 参数“string_list”是字符串列表。
    :return: 不包含输入列表中任何其他字符串的字符串列表。
    """
    result = []
    for i in range(len(string_list)):
        is_contained = False
        for j in range(len(string_list)):
            if i != j and string_list[i] in string_list[j]:
                is_contained = True
                break
        if not is_contained:
            result.append(string_list[i])
    return result

def remove_duplicates_by_strkey(lst):
    """
    函数“remove_duplicates”将字典列表作为输入，并返回一个新列表，其中根据键值对删除了重复的字典。
    :param lst: 参数“lst”是子列表的列表。每个子列表都包含字典。
    :return: 函数“remove_duplicates”返回删除了重复元素的子列表列表。
    """
    unique_keys = set()
    result = []
    for sub_list in lst:
        keys = ''.join([str(sorted(dic.keys())) for dic in sub_list])
        if keys not in unique_keys:
            result.append(sub_list)
            unique_keys.add(keys)
    return result


def remove_simlarity_duplicates(lst,simlar):
    """
    函数“remove_simlarity_duplicates”根据相似性阈值从给定列表中删除重复的子列表。
    
    :param lst: 参数“lst”是子列表的列表。每个子列表都包含字典。
    :return: 函数“remove_simlarity_duplicates”返回删除了重复元素的子列表列表。
    """
    unique_keys = set()
    result = []
    for sub_list in tqdm(lst):
        # `keys = ''.join([str(sorted(dic.items())) for dic in sub_list])` 行正在创建 `sub_list`
        # 中每个字典中已排序键值对的字符串表示形式。
        keys = ''.join([str(sorted(dic.keys())) for dic in sub_list])
        
        is_duplicate = False
        # 该代码块正在检查当前的“sub_list”是否重复。它迭代“unique_keys”集合中的每个“unique_key”，并检查“keys”（表示当前“sub_list”的已排序键值对）是否等于“unique_key”，或者“keys”之间是否相似`
        # 并且 `unique_key` 大于或等于 `simlar` 阈值。如果任一条件为真，则会将“is_duplicate”标志设置为 True
        # 并跳出循环。这确保只有唯一的“sub_lists”被添加到结果列表中，并防止包含重复项。
        for unique_key in unique_keys:
            if keys in unique_key    or edit_distance(keys, unique_key) >= simlar:
                is_duplicate = True
                break
        
        # 代码块 `if not is_duplicate: result.append(sub_list) unique_keys.add(keys)` 正在检查当前 sub_list
        # 是否重复。如果不重复，则将 sub_list 添加到结果列表中，并将键添加到 unique_keys 集中。这可确保仅将唯一的 sub_lists 添加到结果列表中，并防止包含重复项。
        if not is_duplicate:
            result.append(sub_list)
            unique_keys.add(keys)
    return result

def converter(tmp):
    """
    函数“converter”将嵌套的字典列表作为输入，将每个字典转换为新格式，计算每个子列表的平均字典数量，并返回转换后的列表和平均值。
    
    :param tmp: 参数“tmp”是一个列表列表，其中每个内部列表都包含字典。每个字典代表一个提示及其相应的响应。
    :return: 函数“converter”返回一个包含两个元素的元组：“result”和“avg”。 `result` 是一个字典列表，其中每个字典都有两个键：“提示”和“响应”。 `avg`
    是输入 `tmp` 的每个子列表中字典的平均数量。
    """
    result = []
    for sublist in tmp:
        new_sublist = []
        for dic in sublist:
            for key, value in dic.items():
                new_sublist.append({'prompt': key, 'response': value})
        result.append(new_sublist)
    avg = sum([len(x) for x in result]) / len(result)
    show(f'初始去重后 avg : {avg:.2f}')
    return result,avg

def remove_duplicates_from_sub(lst):
    """
    函数“remove_duplicates3”通过将每个子列表中的字典转换为字符串并进行比较来从给定列表中删除重复的子列表。
    
    :param lst: 参数“lst”是子列表的列表。每个子列表都包含字典。
    :return: 函数“remove_duplicates3”返回一个列表“result”，其中包含输入列表“lst”中的唯一子列表。
    """
    seen = set()
    result = []
    for sub_list in tqdm(lst):
        # 将子列表中的字典转换为字符串
        keys = [json.dumps(dic, sort_keys=True) for dic in sub_list]
        # 将字符串列表转换为元组，因为元组是可哈希的
        keys = tuple(sorted(keys))
        if keys not in seen:
            result.append(sub_list)
            seen.add(keys)
    return result


def drop_duplicate_byset(tmp):
    """
    函数“drop_dup”从列表列表中删除重复的字典，其中字典被转换为字符串以进行比较。
    :param tmp: 参数“tmp”是一个子列表列表，其中每个子列表包含字典。
    :return: 输入列表“tmp”的修改版本。修改后的版本删除了每个子列表中的任何重复字典。
    """
    result = []
    seen = set()
    for sublist in tmp:
        new_sublist = []
        for dic in sublist:
            # 将字典转换为字符串，因为字典是不可哈希的
            dic_str = str(dic)
            if dic_str not in seen:
                new_sublist.append(dic)
                seen.add(dic_str)
        result.append(new_sublist)
    return result


def show(content,bar=True):
    if not bar:
        print(f'******************************{content}***************************************')
    else:
        table_data = [[content]]
        table = SingleTable(table_data)
        table.inner_row_border = True  # 启用内部行边框
        # print_code_in_box(content)
        print(table.table)

def rm_prefix(data):
    # 将二维列表转换为一维列表
    flattened_list = [item for sublist in data for item in sublist]
    # print(f'flattened_list:{flattened_list}')
    # 处理某逻辑，这里简单示范将每个元素乘以2
    for item in tqdm(flattened_list):
        item = remove_common_prefix_from_prompt_single(item)
    
    # 还原为原来的二维列表
    restored_list = []
    sublist_length = len(data[0])
    # 代码片段“for i in range(0, len(processed_list), sublist_length):”是一个 for
    # 循环，它以“sublist_length”的步长迭代一系列索引。
    for i in range(0, len(processed_list), sublist_length):
        sublist = processed_list[i:i+sublist_length]
        restored_list.append(sublist)
    # print(f'restored_list:{restored_list}')
    return restored_list


def remove_common_prefix_from_prompt_single(data):
    # 找出所有prompt字段的公共前缀
    common_prefix = os.path.commonprefix([item['prompt'] for item in data])
    # 从第二条数据开始，将公共前缀从prompt字段中删除
    for i in range(1, len(data)):
        data[i]['prompt'] = data[i]['prompt'].replace(common_prefix, '', 1)
    return data

def remove_common_prefix_from_prompt_multi(flattened_list):
    ret = []
    show('去除前缀',bar=False)
    for j in tqdm(range(len(flattened_list))):
        # 从第二条数据开始，将公共前缀从prompt字段中删除
        for i in range(j+1, len(flattened_list)):
            # 找出prompt字段的公共前缀
            common_prefix = os.path.commonprefix([flattened_list[j]['prompt'] ,flattened_list[i]['prompt']])
            flattened_list[i]['prompt'] = flattened_list[i]['prompt'].replace(common_prefix, '', 1)
    return flattened_list

def rm_prefix(data):
    # 将二维列表转换为一维列表
    flattened_list = [item for sublist in data for item in sublist]
    # print(f'flattened_list:{flattened_list}')
    # 处理某逻辑
    processed_list = remove_common_prefix_from_prompt_multi(flattened_list)
    
    # 还原为原来的二维列表
    restored_list = []
    
    # 记录每个子列表的长度
    sublist_lengths = [len(sublist) for sublist in data]
    index = 0
    for sublist_length in sublist_lengths:
        sublist = processed_list[index:index+sublist_length]
        restored_list.append(sublist)
        index += sublist_length
    
    return restored_list

